#include <math.h>
#include <allegro.h>

#define PI (atan(1)*4)

int main(void)
{
  float rotation = PI*0.25;
  float elevation = 1.1;
  float zoom = 50.0;
  float right_x, right_y;
  float front_x, front_y;
  float up_x, up_y; 

  float x, y, z, screen_x, screen_y;

  BITMAP *buffer;

  if (allegro_init() != 0)
    return 1;
  install_timer();
  install_keyboard();

  set_color_depth(32);

  if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0) != 0) 
  {
   if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0)
    {
      set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
      allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
      return 1;
    }
  }
  buffer = create_bitmap(SCREEN_W, SCREEN_H);

  while (!key[KEY_ESC])
  {
    clear_bitmap(buffer);

    if (key[KEY_4_PAD]) rotation += 0.01;
    if (key[KEY_6_PAD]) rotation -= 0.01;    
    if (key[KEY_8_PAD]) elevation += 0.01;
    if (key[KEY_2_PAD]) elevation -= 0.01;    
    if (key[KEY_9_PAD]) zoom *= 1.01;    
    if (key[KEY_3_PAD]) zoom *= 0.99;

    //if (key[KEY_7_PAD]) magic += 0.01;
    //if (key[KEY_1_PAD]) magic -= 0.01;    

    /* precalculated vectors */

    /* rotation */
    right_x = cos(rotation) * 1 - sin(rotation) * 0;
    right_y = sin(rotation) * 1 + cos(rotation) * 0;
    front_x = cos(rotation) * 0 - sin(rotation) * 1;
    front_y = sin(rotation) * 0 + cos(rotation) * 1;

    /* elevation */
    right_y *= cos(elevation);
    front_y *= cos(elevation);

    /* camera
     * assuming the camera never spins around its axis we
     * can leave up.x as 0. 
     */
    up_x = 0.0;
    up_y = sin(elevation);

    /* zoom */
    right_x *= zoom;
    right_y *= zoom;
    front_x *= zoom;
    front_y *= zoom;
    up_x *= zoom;
    up_y *= zoom;

    /* painting the dots */
    z = 0.0;
    for (x=-5.0; x<=5.0; x+=1.0)
    {
      for (y=-5.0; y<=5.0; y+=1.0)
      {
        screen_x = x * right_x + y * front_x + z * up_x;
        screen_y = x * right_y + y * front_y + z * up_y; 

        putpixel(buffer, 
                (int)floor(screen_x + SCREEN_W * 0.5), 
                (int)floor(screen_y + SCREEN_H * 0.5),
                makecol(255, 255, 255));

      }
    }

    blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
    yield_timeslice();
  }

  destroy_bitmap(buffer);
  return 0;
}

END_OF_MAIN();

